package designmode.proxy.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 动态代理的原理是：
 * // InvocationHandlerImpl 实现了 InvocationHandler 接口，并能实现方法调用从代理类到委托类的分派转发
 * // 其内部通常包含指向委托类实例的引用，用于真正执行分派转发过来的方法调用
 * InvocationHandler handler = new InvocationHandlerImpl(..);
 *
 * // 通过 Proxy 为包括 Interface 接口在内的一组接口动态创建代理类的类对象
 * Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... });
 *
 * // 通过反射从生成的类对象获得构造函数对象
 * Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });
 *
 * // 通过构造函数对象创建动态代理类实例
 * Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler });
 */
public class CalculatorHandler implements InvocationHandler {

  private Object target; //被代理类

  public Object getInstance(Object target) {
    this.target = target;
    Class clazz = target.getClass();
    Object obj =
        java.lang.reflect.Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(),
            this);
    return obj;
  }

  /**
   * 当代理对象调用真实对象的方法时，其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用：
   * 第一个参数是target,也就是被代理类的对象；第二个参数是方法中的参数
   * 无论calculator中包含多少函数，动态代理只需实现一次
   *
   * @throws Throwable
   */
  @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 这里可以判断方法名做不同的逻辑
    if (method.getName().equals("add")) {
      System.out.println("proxy invoke add...");
    }
    System.out.println("in calculatorhandler, before invocation");

    Object ret = method.invoke(target, args);  //执行被代理类方法

    System.out.println("in calculationhandler, after invocation");
    return ret;
  }
}